#include "GameManager.h"
#include "common_include.h"
#include "BaseState.h"
#include "TitleScreenState.h"
#include "MainMenuState.h"
#include "OptionState.h"
#include "PauseState.h"

GameManager * GameManager::m_pInstance = NULL;

GameManager * GameManager::GetInstance()
{
   if (m_pInstance == NULL)
      m_pInstance = new GameManager;

   return m_pInstance;
}

GameManager::GameManager(void)
{
   m_eCurGameState = STATE_NOTSET;
   m_bGameRunning = false;
   m_iStartTime = 0;
   m_fCurTime = 0.0f;
}


GameManager::~GameManager(void)
{
   Shutdown();
}

void GameManager::Shutdown()
{
   m_eCurGameState = STATE_NOTSET;
   m_bGameRunning = false;

   for(unsigned int iCurState = 0; iCurState < m_vStates.size(); ++iCurState)
   {
      delete m_vStates[iCurState];
      m_vStates[iCurState] = NULL;
   }

   m_vStates.clear();
}

void GameManager::Init()
{
   m_bGameRunning = true;
   m_eCurGameState = STATE_TITLESCREEN;
   m_iStartTime = clock();
   m_fCurTime = ((float)m_iStartTime)/CLOCKS_PER_SEC;
   // TODO: Add all states here
   BaseState * pStates[STATE_MAX] = {new TitleScreenState(), new MainMenuState(), NULL, new OptionState(), new PauseState()};

   // Go through our list of states from above and add them to our game manager's list of states
   for (unsigned int iCurState = 0; iCurState < STATE_MAX; ++iCurState)
   {
      // Don't add invalid state pointers
      if (pStates[iCurState] == NULL)
         continue;

      // Set the first index to the active state (in this case Title Screen)
      if (iCurState == 0)
         pStates[iCurState]->SetActive(true);

      // Push the state onto our list of states
      m_vStates.push_back(pStates[iCurState]);
   }
}

void GameManager::Update()
{
   float fOldTime = m_fCurTime;
   clock_t t = clock();
   m_fCurTime = ((float)t)/CLOCKS_PER_SEC;
   float fDT = m_fCurTime - fOldTime;

   GetInput();
   
   // Process update from all our active states
   for(unsigned int iCurState = 0; iCurState < m_vStates.size(); ++iCurState)
   {
      if (m_vStates[iCurState]->IsActive())
         m_vStates[iCurState]->Update(fDT);
   }

   // TODO: update game systems here: object manager, decision tree manager, etc.
   // NOTE: should the managers be updated in the game states themselves instead? (Something to determine/decide on)

   Render();
}

void GameManager::GetInput()
{
   /*if (GetAsyncKeyState(VK_LBUTTON))
   {
   }

   if (GetAsyncKeyState(VK_UP))
   {
   }
   if (GetAsyncKeyState(VK_DOWN))
   {
   }
   if (GetAsyncKeyState(VK_LEFT))
   {
   }
   if (GetAsyncKeyState(VK_RIGHT))
   {
   }

   if (GetAsyncKeyState(VK_RETURN))
   {
   }*/

   if (GetAsyncKeyState(VK_ESCAPE))
   {
      // TODO: at some point switch this over to pausing the game instead of 
      //       automatically shutting down the game
      SetGameState(STATE_SHUTDOWN);
   }
   
   // Process input from all our active states
   for(unsigned int iCurState = 0; iCurState < m_vStates.size(); ++iCurState)
   {
      if (m_vStates[iCurState]->IsActive())
         m_vStates[iCurState]->GetInput();
   }
}

void GameManager::Render()
{
   // Process render from all our active states
   for(unsigned int iCurState = 0; iCurState < m_vStates.size(); ++iCurState)
   {
      if (m_vStates[iCurState]->IsActive())
         m_vStates[iCurState]->Render();
   }
}

void GameManager::SetGameState(StateList eState)
{
   // If we are setting the state to SHUTDOWN then set the shutdown flag
   if (eState == STATE_SHUTDOWN)
      m_bGameRunning = false;

   // Exit the previous state we were in, if one was set
   BaseState * pState = GetGameStatePtr(m_eCurGameState);
   if (m_eCurGameState != STATE_NOTSET && pState)
      pState->OnExit();

   m_eCurGameState = eState;

   // Cal Enter on the state we are transitioning to, if it is actually a state
   pState = GetGameStatePtr(eState);
   if (eState != STATE_NOTSET && pState)
      pState->OnEnter();
}

BaseState * GameManager::GetGameStatePtr(StateList eState)
{
   std::vector<BaseState *>::iterator itr = m_vStates.begin();

   // Loop through our states looking for the right one
   while (itr != m_vStates.end())
   {
      // Validate the state type
      if ((*itr)->GetStateType() == eState)
         return (*itr);

      // increment our iterator to the next state
      ++itr;
   }
   // Couldn't find the particular state in our list of states, returning NULL
   return NULL;
}
